//
// Created by 朱林 on 2020/5/8.
//
#include <android/log.h>
#include <android/bitmap.h>
#include <jni.h>
#include <string>
#include <vector>
#include <iostream>
#include "base_util.h"
#include "pupilDetect.h"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/types_c.h"
#include "opencv2/core/core.hpp"

#define TAG "eye"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG,__VA_ARGS__)
pupilDetect *detector;


#define PI 3.141592654

extern "C"
JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
    return JNI_VERSION_1_6;
}

extern "C"
JNIEXPORT void JNI_OnUnload(JavaVM *vm, void *reserved) {
    if (NULL != detector) {
        detector->~pupilDetect();
    }
}

extern "C"
JNIEXPORT jboolean JNICALL
Java_com_example_myapplication_Detect_initDetector(JNIEnv *env, jobject thiz, jstring face_path,
                                                   jstring landmark_path, jstring eyesegment_path, jint num_thread) {
    detector = new pupilDetect();
    std::string mnnPath = getFilePath(env, face_path);
    std::string landmarkPath = getFilePath(env, landmark_path);
    std::string eyeSegPath = getFilePath(env, eyesegment_path);
    int img_size = 320;
    float thresh = 0.8f;
    float nms = 0.3f;
    return detector->createInstance(mnnPath, landmarkPath, eyeSegPath, img_size, num_thread, thresh, nms);
}

extern "C"
JNIEXPORT jfloatArray JNICALL
Java_com_example_myapplication_Detect_detectyuv(JNIEnv *env, jobject thiz,
                                   jbyteArray yuv, jint width, jint height) {
    jfloatArray eyeArgs = nullptr;
    jbyte *pBuf = (jbyte *) env->GetByteArrayElements(yuv, 0);
    cv::Mat image = cv::Mat(height + height / 2, width, CV_8UC1, (unsigned char *) pBuf);

    cv::Mat mBgr;
    cv::cvtColor(image, mBgr, CV_YUV2BGR_NV21);
    cv::Mat input;
    cv::Point center(mBgr.cols/2,mBgr.rows/2); //旋转中心
    cv::transpose(mBgr, input);
    cv::flip(input, input, 0);
//    cv::cvtColor(image, mBgr, CV_YUV2RGB_I420);
//    cv::Mat test;
//    cv::normalize(mBgr, test, 1, 0, cv::NORM_MINMAX) ;
//    cv::Mat test_ = test * 255;
//    test_.convertTo(test, CV_8UC3);
//    cv::imwrite("/storage/emulated/0/mnn/model/light.jpg", test);
//    cv::imwrite("/storage/emulated/0/mnn/model/nv12.jpg", image);
//    cv::imwrite("/storage/emulated/0/mnn/model/bgr.jpg", mBgr);
    cv::imwrite("/storage/emulated/0/mnn/model/input.jpg", input);

//    cv::Scalar mean, std;
//    cv::meanStdDev(input, mean, std);
//    cv::meanStdDev(test, mean, std);

    std::vector<std::vector<cv::Point>> eyes = detector->detect(input);

    for(auto &eye : eyes){
        for(auto &point : eye){
            int x = point.x;
            point.x = width - point.y;
            point.y = x;
        }
    }
//    for(auto eye : eyes){
//        for(auto point : eye){
//            cv::circle(mBgr, point, 3, cv::Scalar(0,0,255), 3);
//        }
//    }
//    cv::imwrite("/storage/emulated/0/mnn/model/res.jpg", mBgr);

    env->DeleteLocalRef(yuv);
    size_t num_eyes = eyes.size();
    if (num_eyes > 0){
        size_t eyeSize = 6;
        float *eyes_ = new float[eyeSize*num_eyes];
        for (size_t i=0;i<num_eyes;i++){
            eyes_[i*eyeSize+0]=eyes[i][0].x;
            eyes_[i*eyeSize+1]=eyes[i][0].y;
            eyes_[i*eyeSize+2]=eyes[i][1].x;
            eyes_[i*eyeSize+3]=eyes[i][1].y;
            eyes_[i*eyeSize+4]=eyes[i][2].x;
            eyes_[i*eyeSize+5]=eyes[i][2].y;
        }
        eyeArgs = env->NewFloatArray(eyeSize*num_eyes);
        env->SetFloatArrayRegion(eyeArgs, 0, eyeSize*num_eyes, eyes_);
        delete [] eyes_;
        return eyeArgs;
    }else{
        return env->NewFloatArray(0);
    }
}


extern "C"
JNIEXPORT jfloatArray JNICALL
Java_com_example_myapplication_Detect_detectpath(JNIEnv *env, jobject thiz, jstring img_name) {
    jfloatArray eyeArgs = nullptr;
    std::string path = jstring2str(env, img_name);
    cv::Mat img = cv::imread(path);
    cv::imwrite("/storage/emulated/0/mnn/model/bgr.jpg", img);
    std::vector<std::vector<cv::Point>> eyes = detector->detect(img);
    size_t num_eyes = eyes.size();
    if (num_eyes > 0) {
        size_t eyeSize = 6;
        float *eyes_ = new float[eyeSize*num_eyes];
        for (size_t i = 0; i < num_eyes; i++){
            eyes_[i*eyeSize+0]=eyes[0][0].x;
            eyes_[i*eyeSize+1]=eyes[0][0].y;
            eyes_[i*eyeSize+2]=eyes[0][1].x;
            eyes_[i*eyeSize+3]=eyes[0][1].y;
            eyes_[i*eyeSize+4]=eyes[0][2].x;
            eyes_[i*eyeSize+5]=eyes[0][2].y;
        }
        eyeArgs = env->NewFloatArray(eyeSize*num_eyes);
        env->SetFloatArrayRegion(eyeArgs, 0, eyeSize*num_eyes, eyes_);
        delete [] eyes_;
        return eyeArgs;
    }
    else {
        return env->NewFloatArray(0);
    }
}

extern "C"
JNIEXPORT jfloatArray JNICALL
Java_com_example_myapplication_Detect_detectbyte(JNIEnv *env, jobject thiz, jbyteArray img, jint width, jint height) {
    jfloatArray eyeArgs = nullptr;
    jbyte *pBuf = (jbyte *) env->GetByteArrayElements(img, 0);
    cv::Mat image = cv::Mat(height, width, CV_8UC3, (unsigned char *) pBuf);
    std::vector<std::vector<cv::Point>> eyes = detector->detect(image);
    env->DeleteLocalRef(img);
    size_t num_eyes = eyes.size();
    if (num_eyes > 0){
        size_t eyeSize = 6;
        float *eyes_ = new float[eyeSize*num_eyes];
        for (size_t i=0;i<num_eyes;i++){
            eyes_[i*eyeSize+0]=eyes[0][0].x;
            eyes_[i*eyeSize+1]=eyes[0][0].y;
            eyes_[i*eyeSize+2]=eyes[0][1].x;
            eyes_[i*eyeSize+3]=eyes[0][1].y;
            eyes_[i*eyeSize+4]=eyes[0][2].x;
            eyes_[i*eyeSize+5]=eyes[0][2].y;
        }
        eyeArgs = env->NewFloatArray(eyeSize*num_eyes);
        env->SetFloatArrayRegion(eyeArgs, 0, eyeSize, eyes_);
        delete [] eyes_;
        return eyeArgs;
    }else{
        return env->NewFloatArray(0);
    }
}
